package GA_Test;

import 多无人机架次.TimeCount;

import java.util.ArrayList;
import java.util.Random;

/**
 *本方法用于对同一车辆上的车辆访问顾客与无人机访问顾客点进行交换
 *只对无人机访问顾客点与车辆访问顾客点进行交换
 *
 */
public class Operators_Same_Change { //返回一个全新的种群
     static SpeciesPopulation main_method(SpeciesPopulation new_list, float now_tem){
          SpeciesPopulation new_pop = new SpeciesPopulation();
          big:
          for (int i = 0; i < new_list.specPopu.size(); i++) {
               SpeciesIndividual now_individual =new_list.specPopu.get(i);//拿出一个个体

                    for(int k = 0;k<now_individual.TruckGenes.size();k++){ //也别随机选了  就是把每一个车辆路径下的最优找出来
                    ArrayList<Integer> truck_route =  (ArrayList<Integer>) now_individual.TruckGenes.get(k);
                    ArrayList<Integer> drone_route = (ArrayList<Integer>) now_individual.DroneGenes.get(k);
                    if (drone_route.size() != 0) { //不等于0 说明 当前选的这车上面有无人机架次
                         exchange(truck_route, drone_route); //调用这个方法实现对指定 无人机的路径更改
                         break;
                    } else { //如果当前车辆上没有无人机架次的话  就继续找另一辆车
                         continue big;
                    }
               }
               now_individual.calFitness();
               new_pop.add(now_individual.clone());
               //这里的模拟退火规则感觉没有什么意义 因为但凡发生交换 个体的性能肯定是提升了 也就是说 这个算子是找某个车辆路线中交换访问顾客点 的最优交换方式
//               if (new_runtime <= old_time) { //如果新个体的时间优于旧个体 那么就接受新个体
//                    new_pop.add(now_individual.clone());
//                    continue big;
//               } else { //如果不是的话 利用模拟退火规则接受这个个体
//                    Random random = new Random();
//                    double value = Math.exp((new_runtime - old_time) / now_tem);
//                    double r = random.nextInt(1);//生成一个0-1之间的随机数
//                    if (r > value) {//如果随机生成的概率大于这个 模拟退火的概率值  那么就接受这个劣解
//                         new_pop.add(now_individual.clone());
//                         continue big;
//                    } else {//这里本来是还原个体 现在不需要还原 因为如果没有发生优化 个体在交叉时就进行了还原 即只要交叉 必定是优化过的
//                         for (int k = 0; k < old_drone_route.size(); k++) {
//                              ArrayList<Integer> al = (ArrayList<Integer>) now_individual.DroneGenes.get(which_drone);
//                              al.set(k, old_drone_route.get(k)); //不接受这个个体   就把这个个体的更改进行还原
//                         }
//                         new_pop.add(now_individual.clone());
//                    }
//               }
          }

          return new_list;
     }

     private static void exchange(ArrayList<Integer> truck_route, ArrayList<Integer> drone_route) {
          double best = TimeCount.timeCount(truck_route,drone_route);//将当前传进来的这个组合的时间设为最好的
          ArrayList<Integer> message = new ArrayList<>();
          for (int t = 0; t < truck_route.size(); t++) {
               for (int d = 0; d < drone_route.size(); d++) {
                    if (truck_route.get(t) == drone_route.get(d)) {
                         message.add(t);
                         message.add(d);
                         message.add(truck_route.get(t));
                    }
               }
          }
          if(message.size()<6){ //如果当前  车辆与无人机未够成 有效的架次 则直接退出方法
               return;
          }
               int truck_off1_position = message.get(0); //车辆访问路径中 无人机第一次起飞的位置
               int drone_off1_position = message.get(1);// 无人机路径中  无人机第一次起飞的位置
               int off1 = message.get(2);// 起飞的客户点
               int truck_down1_position = message.get(3);//车辆访问路径中 无人机第一次降落的位置
               int drone_down1_position = message.get(4);//无人机路径中 无人机第一次降落的位置
               int down1 = message.get(5);//降落的客户点
               int truck_off2_position = 0;
               int drone_off2_position = 0;
               int off2 = 0;
               int truck_down2_position = 0;
               int drone_down2_position = 0;
               int down2 = 0;
           if (message.size() > 6) {
               truck_off2_position = message.get(6);
               drone_off2_position = message.get(7);
               off2 = message.get(8);
//            System.out.println(truck_route);
//            System.out.println(drone_route);
//            System.out.println(message);
               truck_down2_position = message.get(9);
               drone_down2_position = message.get(10);
               down2 = message.get(11);
          }
              //把无人机与车辆的访问顾客点分别提取出来


               //随机从车辆访问顾客中挑一个点，从无人机访问顾客中挑一个点进行交换
               for(int k = 0;k<10;k++) { //这里的循环是想 多遍历几次交换  取最好的值
                    ArrayList<Integer> truck_service = new ArrayList<>();
                    ArrayList<Integer> drone_service = new ArrayList<>();
                    for(int m = drone_off1_position+1;m<drone_down1_position;m++){
                         drone_service.add(drone_route.get(m));
                    }
                    for(int m = drone_off2_position+1;m<drone_down2_position;m++){
                         drone_service.add(drone_route.get(m));
                    }
                    if(truck_off2_position == 0){//此时说明只有一个架次
                         for(int m = 0;m<truck_off1_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_off1_position+1;m<truck_down1_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_down1_position+1;m<truck_route.size();m++){
                              truck_service.add(truck_route.get(m));
                         }
                    }else{//两个架次的情况
                         for(int m = 0;m<truck_off1_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_off1_position+1;m<truck_down1_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_down1_position+1;m<truck_off2_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_off2_position+1;m<truck_down2_position;m++){
                              truck_service.add(truck_route.get(m));
                         }
                         for(int m = truck_down2_position+1;m<truck_route.size();m++){
                              truck_service.add(truck_route.get(m));
                         }
                    }
                    Random random =  new Random();
                    if(truck_service.size()!=0 && drone_service.size()!=0) {
                         int truck_point = truck_service.get(random.nextInt(truck_service.size()));
                         int truck_point_position = 0;

                         int drone_point = drone_service.get(random.nextInt(drone_service.size()));
                         int drone_point_position = 0;

                         //找到这个车辆节点与无人机节点的所在位置    然后进行对应交换
                         for (int n = 0; n < truck_route.size(); n++) {
                              if (truck_point == truck_route.get(n)) {
                                   truck_point_position = n;
                              }
                         }
                         for (int n = 0; n < drone_route.size(); n++) {
                              if (drone_point == drone_route.get(n)) {
                                   drone_point_position = n;
                              }
                         }

                         truck_route.set(truck_point_position, drone_point);
                         drone_route.set(drone_point_position, truck_point);
                         //这里完成交换 完成后 应当将service 集合中内容清除  根据交换结果 进行重新生成

                         //进行交换后的约束检查
                         if (isok(truck_route, drone_route)) {//如果交换后满足约束
                              double time = TimeCount.timeCount(truck_route, drone_route);//计算交换后的时间
                              if (time < best) {
                                   best = time;
                              } else {
                                   truck_route.set(truck_point_position, truck_point);
                                   drone_route.set(drone_point_position, drone_point);//交换回去
                              }
                         } else { //不满足约束的话  将车辆路径进行还原 继续进行交换
                              truck_route.set(truck_point_position, truck_point);
                              drone_route.set(drone_point_position, drone_point);//交换完成
                         }
                    }
               }
          }
     private static boolean isok(ArrayList<Integer> truck, ArrayList<Integer> drone) {
          boolean flag = true;

          ArrayList<Integer> message = new ArrayList<>();
          for (int t = 0; t < truck.size(); t++) {
               for (int d = 0; d < drone.size(); d++) {
                    if (truck.get(t) == drone.get(d)) {
                         message.add(t);
                         message.add(d);
                         message.add(truck.get(t));
                    }
               }
          }
          int truck_off1_position = message.get(0); //车辆访问路径中 无人机第一次起飞的位置
          int drone_off1_position = message.get(1);// 无人机路径中  无人机第一次起飞的位置
          int off1 = message.get(2);// 起飞的客户点

          int truck_down1_position = message.get(3);//车辆访问路径中 无人机第一次降落的位置
          int drone_down1_position = message.get(4);//无人机路径中 无人机第一次降落的位置
          int down1 = message.get(5);//降落的客户点
          int truck_off2_position = 0;
          int drone_off2_position = 0;
          int off2 = 0;
          int truck_down2_position = 0;
          int drone_down2_position = 0;
          int down2 = 0;
          if (message.size() > 6) {
               truck_off2_position = message.get(6);
               drone_off2_position = message.get(7);
               off2 = message.get(8);
               truck_down2_position = message.get(9);
               drone_down2_position = message.get(10);
               down2 = message.get(11);
          }
          double drone_distance1 =0; int cap1 = 0;
          double drone_distance2 =0; int cap2 = 0;
          for(int k =drone_off1_position;k<drone_down1_position;k++){
               drone_distance1 += GAData.disCollection[drone.get(k)][drone.get(k+1)]; //无人机第一架次距离计算
          }
          for(int k = drone_off1_position+1;k<drone_down1_position;k++){//无人机第一架次载重计算
               cap1 += GAData.cusInfo[k].demand;
          }
          if(drone_distance1>GAData.distanceDrone || cap1>GAData.capacityDrone){
               flag = false;
          }
          if(drone_off2_position!=0){
               for(int k =drone_off2_position;k<drone_down2_position;k++){
                    drone_distance2 += GAData.disCollection[drone.get(k)][drone.get(k+1)]; //无人机第一架次距离计算
               }
               for(int k = drone_off2_position+1;k<drone_down2_position;k++){//无人机第二架次载重计算
                    cap2 += GAData.cusInfo[k].demand;
               }
          }
          if(drone_distance2>GAData.distanceDrone || cap2>GAData.capacityDrone){
               flag = false;
          }
          return flag;
     }
     }
